package com.authine.cloudpivot.ext.utils.boQuery;

import cn.hutool.core.bean.BeanUtil;
import com.alibaba.cola.dto.SingleResponse;
import com.authine.cloudpivot.data.support.PageImpl;
import com.authine.cloudpivot.ext.utils.HttpClients;
import com.authine.cloudpivot.ext.utils.TypeReferenceUtils;
import com.authine.hermes.app.launcher.service.BOService;
import com.authine.mvp.app.launcher.domain.utills.ApplicationContextUtils;
import com.authine.mvp.app.launcher.dto.bo.query.ListBOQuery;
import com.authine.mvp.app.launcher.dto.bo.query.expression.ComplexCondition;
import com.authine.mvp.app.launcher.dto.bo.query.expression.Nature;
import com.authine.mvp.app.launcher.dto.bo.query.expression.Operator;
import com.authine.mvp.app.launcher.dto.bo.query.expression.SimpleCondition;
import com.authine.mvp.app.launcher.dto.bo.response.BOList;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 基于 云枢 BoService 查询, 查询其他应用里的领域模型数据, 调用rpc 传其他应用的appCode
 */
public class BoQueryUtils {

    private BOService boService = ApplicationContextUtils.getBean(BOService.class);

    private ListBOQuery listBOQuery;


    private BoQueryUtils(ListBOQuery query) {
        listBOQuery = query;
    }


    public static BoQueryUtils Builder(String schemaCode) {
        ListBOQuery listBOQuery = new ListBOQuery();
        listBOQuery.setSchemaCode(schemaCode);
        BoQueryUtils boQueryUtils = new BoQueryUtils(listBOQuery);
        return boQueryUtils;
    }

    public BoCondition condition() {
        return new BoCondition();
    }


    public <T> PageImpl<T> listBO(Class<T> clazz) {

        return toPageImpl(listBO(), clazz);
    }

    public SingleResponse<BOList> listBO() {
        return boService.list(listBOQuery);
    }

    private <T> PageImpl<T> toPageImpl(SingleResponse<BOList> singleResponse, Class<T> clazz) {

        int total = singleResponse.getData().getTotal();
        List<T> collect;
        if (total > 0) {
            collect = singleResponse.getData().getData().stream().map(a -> BeanUtil.mapToBean(a, clazz, true)).collect(Collectors.toList());
        } else {
            collect = Collections.EMPTY_LIST;
        }
        return new PageImpl<>(total, collect);
    }

    public class Rpc {
        private String appCode;

        Rpc(String appCode) {
            this.appCode = appCode;
        }

        public <T> PageImpl<T> listBO(Class<T> clazz) {

            return toPageImpl(listBO(), clazz);

        }

        private Rpc() {
        }

        ;

        public SingleResponse<BOList> listBO() {
            String execute = HttpClients.execute(HttpClients.getUrl(appCode, HttpClients.listBo), BeanUtil.beanToMap(listBOQuery));
            return TypeReferenceUtils.readValueToSingleResponseList(execute);
        }

    }


    public class BoCondition {
        ComplexCondition complexCondition;

        private BoCondition() {
            complexCondition = new ComplexCondition();
            complexCondition.setNature(Nature.AND);
            complexCondition.setConditions(new ArrayList<>());
            listBOQuery.setCondition(complexCondition);
        }

        SimpleCondition getSimple(String name, Operator opt, Object val) {
            return new SimpleCondition(name, opt, val);
        }

        public BoQueryUtils End() {
            return BoQueryUtils.this;
        }

        public Rpc rpc(String appCode) {
            return new Rpc(appCode);
        }

        public BoCondition page(int pageIndex, int pageSize) {
            listBOQuery.setPageIndex(pageIndex);
            listBOQuery.setPageSize(pageSize);
            return this;
        }

        public BoCondition eq(String name, Object val) {
            complexCondition.getConditions().add(getSimple(name, Operator.EQ, val));
            return this;
        }

        public BoCondition notEq(String name, Object val) {
            complexCondition.getConditions().add(getSimple(name, Operator.NOT_EQ, val));
            return this;
        }

        public BoCondition in(String name, List val) {
            complexCondition.getConditions().add(getSimple(name, Operator.IN, val));
            return this;
        }

        public BoCondition notIn(String name, List val) {
            complexCondition.getConditions().add(getSimple(name, Operator.NOT_IN, val));
            return this;
        }

        public BoCondition gt(String name, Object val) {
            complexCondition.getConditions().add(getSimple(name, Operator.GT, val));
            return this;
        }

        public BoCondition gte(String name, Object val) {
            complexCondition.getConditions().add(getSimple(name, Operator.GTE, val));
            return this;
        }

        public BoCondition lt(String name, Object val) {
            complexCondition.getConditions().add(getSimple(name, Operator.LT, val));
            return this;
        }

        public BoCondition lte(String name, Object val) {
            complexCondition.getConditions().add(getSimple(name, Operator.LTE, val));
            return this;
        }

        public BoCondition isNotNull(String name) {
            complexCondition.getConditions().add(getSimple(name, Operator.IS_NOT_NULL, null));
            return this;
        }

        public BoCondition isNull(String name) {
            complexCondition.getConditions().add(getSimple(name, Operator.IS_NULL, null));
            return this;
        }

        public BoCondition like(String name, Object val) {
            complexCondition.getConditions().add(getSimple(name, Operator.LIKE, val));
            return this;
        }

        public BoCondition notlike(String name, Object val) {
            complexCondition.getConditions().add(getSimple(name, Operator.NOT_LIKE, val));
            return this;
        }
    }
}
